home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 42 / Amiga Format AFCD42 (Issue 126, Aug 1999).iso / -serious- / comms / other / micq-0.4.0 / micq.c < prev    next >
C/C++ Source or Header  |  1999-05-14  |  15KB  |  514 lines

  1. /*********************************************
  2. **********************************************
  3. This is the main ICQ file. Currently it
  4. logs in and sits in a loop. It can receive
  5. messages and keeps the connection alive.
  6. Use crtl-break to exit.
  7.  
  8. This software is provided AS IS to be used in
  9. whatever way you see fit and is placed in the
  10. public domain.
  11.  
  12. Author : Matthew Smith April 19, 1998
  13. Contributors : Nicolas Sahlqvist April 27, 1998
  14.                Ulf Hedlund (guru@slideware.com) April 28, 1998
  15.             Michael Ivey May 4, 1998
  16.             Michael Holzt May 5, 1998
  17.  
  18. Changes :
  19.    4-28-98 support for WIN32 [UH]
  20.    4-20-98 added variable time_delay between keep_alive packets mds
  21.    4-20-98 added instant message from server support mds
  22.    4-21-98 changed so that long ( 250+ characters ) messages work
  23.             new maximum is ~900 which is hopefully big enough.
  24.             When I know more about udp maybe I can come up with
  25.             a general solution. mds I now think ICQ has a max that is
  26.             smaller than this so everything is ok mds I now think that
  27.             the icq client's maximum is arbitrary and can be ignored :)
  28.    4-23-98 Added beginnings of a user interface
  29.    4-26-98 Changed the version to 0.2a :)
  30.    4-27-98 Nicco added feature to use nick names to log in
  31.    5-05-98 Authorization Messages
  32.    5-13-98 Added time stamps for most things.
  33.    6-17-98 Changed condition on which we should send auto_reply message. Fryslan
  34.    6-18-98 Added different auto reply messages for different status types see also ui.c and util.c Fryslan
  35.    6-20-98 Added an alter command to alter your command names online. Fryslan
  36. **********************************************
  37. **********************************************/
  38. #include "micq.h"
  39. #include "datatype.h"
  40. #include "msg_queue.h"
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43. #include <limits.h>
  44.  
  45. #ifdef _WIN32
  46. #include <conio.h>
  47. #include <io.h>
  48. #include <winsock2.h>
  49. #include <time.h>
  50. #else
  51. #include <unistd.h>
  52. #include <netinet/in.h>
  53. #include <sys/types.h>
  54. #include <sys/stat.h>
  55. #include <sys/socket.h>
  56. #include <arpa/inet.h>
  57. #include <netdb.h>
  58. #include <sys/time.h>
  59. #include <sys/wait.h>
  60. #include "mreadline.h"
  61. #endif
  62. #include <fcntl.h>
  63. #include <time.h>
  64. #include <stdarg.h>
  65. #include <string.h>
  66. #include <ctype.h>
  67. #include <assert.h>
  68. #ifdef __SASC
  69. #include <proto/dos.h>
  70. #include <proto/exec.h>
  71. #include "amiga-dt.h"
  72. #endif
  73.  
  74.  
  75. BYTE Sound = SOUND_ON; /* Beeps on by default */
  76. BYTE Sound_Str[150];  /* the command to run from the shell to play sound files */
  77. BOOL Russian = FALSE; /* Do we do kio8-r <->Cp1251 codeset translation? */
  78. BOOL Logging = TRUE;  /* Do we log messages to ~/micq_log?  This should probably have different levels */
  79. BOOL Color = TRUE; /* Do we use ANSI color? */
  80. BOOL Quit = FALSE;    /* set when it's time to exit the program */
  81. BOOL Verbose = FALSE; /* this is displays extra debuging info */
  82. BOOL serv_mess[ 1024 ]; /* used so that we don't get duplicate messages with the same SEQ */
  83. WORD last_cmd[ 1024 ]; /* command issued for the first 1024 SEQ #'s */
  84. /******************** if we have more than 1024 SEQ this will need some hacking */
  85. WORD seq_num = 1;  /* current sequence number */
  86. DWORD our_ip = 0x0100007f; /* localhost for some reason */
  87. DWORD our_port; /* the port to make tcp connections on */
  88. /************ We don't make tcp connections yet though :( */
  89. DWORD UIN; /* current User Id Number */
  90. BOOL Contact_List = FALSE; /* I think we always have a contact list now */
  91. Contact_Member Contacts[ 100 ]; /* no more than 100 contacts max */
  92. int Num_Contacts=0;
  93. DWORD Current_Status=STATUS_OFFLINE;
  94. DWORD last_recv_uin=0;
  95. char passwd[100];
  96. char server[100];
  97. DWORD set_status;
  98. DWORD remote_port;
  99. BOOL Done_Login=FALSE;
  100. BOOL auto_resp=FALSE;
  101. char auto_rep_str_dnd[450] = { "Don't page me, my head is hurting!" };
  102. char auto_rep_str_away[450] = { "I told you I wasn't here!" };
  103. char auto_rep_str_na[450] = { "Working, working always working..." };
  104. char auto_rep_str_occ[450] = { "I am working on opening this beer so I am busy." };
  105. char auto_rep_str_inv[450] = { "So you can see me, so you can't!" };
  106. char message_cmd[16];
  107. char info_cmd[16];
  108. char quit_cmd[16];
  109. char reply_cmd[16];
  110. char again_cmd[16];
  111. char add_cmd[16];
  112.  
  113. char list_cmd[16];
  114. char away_cmd[16];
  115. char na_cmd[16];
  116. char dnd_cmd[16];
  117. char online_cmd[16];
  118. char occ_cmd[16];
  119. char ffc_cmd[16];
  120. char inv_cmd[16];
  121. char status_cmd[16];
  122. char auth_cmd[16];
  123. char auto_cmd[16];
  124. char change_cmd[16];
  125. char search_cmd[16];
  126. char save_cmd[16];
  127. char alter_cmd[16];
  128. char msga_cmd[16];
  129. char url_cmd[16];
  130. char update_cmd[16];
  131. char rand_cmd[16];
  132. char color_cmd[16];
  133. char sound_cmd[16];
  134.  
  135. /*** auto away values ***/
  136. int idle_val=0;
  137. int idle_flag=0;
  138. #define away_time 600
  139.  
  140. unsigned int next_resend;
  141.  
  142. /*/////////////////////////////////////////////
  143. // Connects to hostname on port port
  144. // hostname can be DNS or nnn.nnn.nnn.nnn
  145. // write out messages to the FD aux */
  146. int Connect_Remote( char *hostname, int port, FD_T aux )
  147. {
  148.  
  149.    int conct, length;
  150.    int sok;
  151.    struct sockaddr_in sin;  /* used to store inet addr stuff */
  152.    struct hostent *host_struct; /* used in DNS lookup */
  153.  
  154. #if 1
  155.     sin.sin_addr.s_addr = inet_addr( hostname ); 
  156.       if ( sin.sin_addr.s_addr  == -1 ) /* name isn't n.n.n.n so must be DNS */
  157. #else
  158.  
  159.     if ( inet_aton( hostname, &sin.sin_addr )  == 0 ) /* checks for n.n.n.n notation */
  160. #endif
  161.     {
  162.        host_struct = gethostbyname( hostname );/* name isn't n.n.n.n so must be DNS */
  163.       if ( host_struct == NULL )
  164.       {
  165.          if ( Verbose )
  166.          {
  167.             M_fdprint( aux, "Shakespeare couldn't spell why should I?\n" );
  168.             M_fdprint( aux, " Especially something like %s\n", hostname );
  169.             /*herror( "Can't find hostname" );*/
  170.          }
  171.          return 0;
  172.       }
  173.        sin.sin_addr = *((struct in_addr *)host_struct->h_addr);
  174.    }
  175.     sin.sin_family = AF_INET; /* we're using the inet not appletalk*/
  176.     sin.sin_port = htons( port );    /* port */
  177.     sok = socket( AF_INET, SOCK_DGRAM, 0 );/* create the unconnected socket*/
  178.    if ( sok == -1 ) 
  179.    {
  180.       perror( "Socket creation failed" );
  181.       exit( 1 );
  182.    }   
  183.    if ( Verbose )
  184.    {
  185.       M_fdprint( aux, "Socket created attempting to connect\n" );
  186.    }
  187.     conct = connect( sok, (struct sockaddr *) &sin, sizeof( sin ) );
  188.     if ( conct == -1 )/* did we connect ?*/
  189.     {
  190.       if ( Verbose )
  191.       {
  192.           M_fdprint( aux, " Conection Refused on port %d at %s\n", port, hostname );
  193.          #ifdef FUNNY_MSGS
  194.             M_fdprint( aux, " D'oh!\n" );
  195.          #endif
  196.           perror( "connect" );
  197.       }
  198.        return 0;
  199.     }
  200.    length = sizeof( sin ) ;
  201.    getsockname( sok, (struct sockaddr *) &sin, &length );
  202.    our_ip = sin.sin_addr.s_addr;
  203.    our_port = sin.sin_port;
  204.    if (Verbose )
  205.    {
  206.       #ifdef FUNNY_MSGS
  207.          M_fdprint( aux, "Our port is %d, take her to sea Mr. Mordoch.\n", ntohs( sin.sin_port ) );
  208.       #else
  209.          M_fdprint( aux, "The port that will be used for tcp ( not yet implemented ) is %d\n", ntohs( sin.sin_port ) );
  210.       #endif
  211.    }
  212.    if ( Verbose )
  213.    {
  214.       M_fdprint( aux, "Connected to %s, waiting for response\n", hostname );
  215.    }
  216.    return sok;
  217. }
  218.  
  219.  
  220. /******************************************
  221. Handles packets that the server sends to us.
  222. *******************************************/
  223. void Handle_Server_Response( SOK_T sok )
  224. {
  225.    srv_net_icq_pak pak;
  226.    static DWORD last_seq=-1;
  227.    int s;
  228.    
  229.    s = SOCKREAD( sok, &pak.head.ver, sizeof( pak ) - 2  );
  230.    if ( s < 0 )
  231.        return;
  232.       
  233. #if 0
  234.    M_print( "Cmd : %04X\t",Chars_2_Word( pak.head.cmd ) );
  235.    M_print( "Ver : %04X\t",Chars_2_Word( pak.head.ver ) );
  236.    M_print( "Seq : %08X\t",Chars_2_DW( pak.head.seq ) );
  237.    M_print( "Ses : %08X\n",Chars_2_DW( pak.head.session ) );
  238. #endif
  239.   if ( Chars_2_DW( pak.head.session ) != our_session ) {
  240.      if ( Verbose ) {
  241.            R_undraw();
  242.         M_print( "Got a bad session ID %08X with CMD %04X ignored.\n", 
  243.             Chars_2_DW( pak.head.session ), Chars_2_Word( pak.head.cmd ) );
  244.     R_redraw();
  245.      }
  246.      return;
  247.   }
  248.   /* !!! TODO make a check checksum routine to verify the packet further */
  249. /*   if ( ( serv_mess[ Chars_2_Word( pak.head.seq2 ) ] ) && 
  250.       ( Chars_2_Word( pak.head.cmd ) != SRV_NEW_UIN ) )*/
  251.    if ( ( last_seq == Char